package com.freedom.web.mymvc.route;

import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.freedom.web.mymvc.utils.LoggerUtils;
import com.freedom.web.mymvc.utils.ConstantsUtils;

import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;

@SuppressWarnings("resource")
public class RouteBuilder {
	// logger
	private static final Logger logger = LogManager.getLogger(RouteBuilder.class);
	private HashMap<String, Route> routesForFullMatch = new HashMap<String, Route>();// 只读情况下，不加锁，效率最高
	private HashMap<String, Route> routesForPrefixMatch = new HashMap<String, Route>();// 只读情况下，不加锁，效率最高
	private HashMap<String, Route> routesForSuffixMatch = new HashMap<String, Route>();// 只读情况下，不加锁，效率最高

	private RouteBuilder() {
	}

	public Route getRoute(String key) {
		//
		LoggerUtils.debug(logger, "try to find route for: " + key);
		Route result = null;
		// 0)全匹配优先级最高
		result = routesForFullMatch.get(key);
		if (null != result) {// 全匹配找到了，就返回
			LoggerUtils.debug(logger, "find full match route for " + key);
			return result;
		}
		// 1)尝试前缀匹配
		Iterator<String> prefixKeys = routesForPrefixMatch.keySet().iterator();
		while (prefixKeys.hasNext()) {
			String prefixKey = prefixKeys.next();
			if (null != prefixKey && key.startsWith(prefixKey)) {
				LoggerUtils.debug(logger, "find prefix match route for " + key);
				return routesForPrefixMatch.get(prefixKey);
			}
		}
		// 2)尝试后缀匹配
		Iterator<String> suffixKeys = routesForSuffixMatch.keySet().iterator();
		while (suffixKeys.hasNext()) {
			String suffixKey = suffixKeys.next();
			if (null != suffixKey && key.endsWith(suffixKey)) {
				LoggerUtils.debug(logger, "find suffix match route for " + key);
				return routesForSuffixMatch.get(suffixKey);
			}
		}
		// 3)没找到
		LoggerUtils.error(logger, "find no match route for " + key);
		return null;
	}

	@SuppressWarnings("rawtypes")
	public void addRule(RouteType type, String path, String className) throws Exception {
		// 判断这个类是否是WorkerClass的实现
		Class<?> currentClass = Class.forName(className);
		if (false == com.freedom.web.mymvc.common.SystemInterface.class.isAssignableFrom(currentClass)) {
			throw new Exception("class: " + className
					+ " is not valid...should be interface implementation of (com.freedom.web.mymvc.route.MyRoute)");
		}
		// 测试通过，获取实例
		Object obj = currentClass.newInstance();
		// 获取方法
		Class[] argsClass = new Class[2];
		argsClass[0] = FullHttpRequest.class;
		argsClass[1] = FullHttpResponse.class;
		Method method = currentClass.getMethod("service", argsClass);
		// 构造route,存起来
		Route route = new Route(path, obj, method);
		//
		// 选择合适的map
		if (type == RouteType.FULL_MATCH)
			routesForFullMatch.put(path, route);
		else if (type == RouteType.PREFIX_MATCH) {
			routesForPrefixMatch.put(path, route);
		} else if (type == RouteType.SUFFIX_MATCH) {
			routesForSuffixMatch.put(path, route);
		}
		// 结束,等待被调用
		// 执行时只需要method.invoke(obj, args);
	}

	public static RouteBuilder instance = null;

	public static RouteBuilder getInstance() {
		return instance;
	}

	static {
		RouteBuilder route = new RouteBuilder();
		String routeFile = ConstantsUtils.ROUTE_FILE;
		LoggerUtils.info(logger, "try to parse route file-" + routeFile);
		// 按行读取
		try {
			FileReader reader = new FileReader(routeFile);
			BufferedReader br = new BufferedReader(reader);
			String str = null;
			while ((str = br.readLine()) != null) {
				str = str.trim();
				if (0 == str.length() || str.startsWith("#")) {
					continue;
				}
				// 有合法值
				String[] kv = str.split("\\s+");
				if (null == kv || (kv.length != 2 && kv.length != 3)) {
					LoggerUtils.error(logger, "kv:" + kv.length);
					throw new Exception("parse " + str + " error");
				}
				// 如果为3，则必须满足条件,prefix | suffix 二选一，别的不认 :)
				if (kv.length == 3) {
					if (false == kv[0].trim().equalsIgnoreCase("prefix")//
							&& false == kv[0].trim().equalsIgnoreCase("suffix")) {
						LoggerUtils.error(logger, "kv:" + kv.length);
						throw new Exception("parse " + str + " error");
					}
				}
				// 选则合适的route加进去
				if (2 == kv.length) {
					route.addRule(RouteType.FULL_MATCH, kv[0], kv[1]);
				} else if (kv[0].trim().equalsIgnoreCase("prefix")) {
					route.addRule(RouteType.PREFIX_MATCH, kv[1], kv[2]);
				} else if (kv[0].trim().equalsIgnoreCase("suffix")) {
					route.addRule(RouteType.SUFFIX_MATCH, kv[1], kv[2]);
				}
				// 结束

			}
			// 释放文件句柄
			br.close();
			reader.close();
			// 赋值
			instance = route;
		} catch (Exception e) {
			LoggerUtils.error(logger, e.toString());
			System.exit(-1);
		}
	}

}